﻿using System;

namespace ShapeFactoryDemo
{
    public abstract class Shape
    {
        public abstract double CalculateArea();
        public abstract bool IsValid { get; }
    }

    class ShapeFactory
    {
        private Random _rand = new Random();

        public Shape CreateShape()
        {
            switch (_rand.Next(3))
            {
                case 0: return new Rectangle(_rand.Next(1, 10), _rand.Next(1, 10));
                case 1: return new Square(_rand.Next(1, 10));
                case 2: return CreateValidTriangle();
                default: throw new InvalidOperationException();
            }
        }

        private Triangle CreateValidTriangle()
        {
            while (true)
            {
                var a = _rand.Next(1, 10);
                var b = _rand.Next(1, 10);
                var c = _rand.Next(1, 10);
                if (new Triangle(a, b, c).IsValid) return new Triangle(a, b, c);
            }
        }
    }

    class Rectangle : Shape
    {
        public double Length { get; }
        public double Width { get; }

        public Rectangle(double l, double w) => (Length, Width) = (l, w);
        public override bool IsValid => Length > 0 && Width > 0;
        public override double CalculateArea() => Length * Width;
    }

    class Square : Rectangle
    {
        public Square(double s) : base(s, s) { }
    }

    class Triangle : Shape
    {
        public double A { get; }
        public double B { get; }
        public double C { get; }

        public Triangle(double a, double b, double c) => (A, B, C) = (a, b, c);
        public override bool IsValid => (A + B > C) && (B + C > A) && (C + A > B);

        public override double CalculateArea()
        {
            double p = (A + B + C) / 2;
            return Math.Sqrt(p * (p - A) * (p - B) * (p - C));
        }
    }

    class Program
    {
        static void Main()
        {
            var factory = new ShapeFactory();
            double total = 0;

            for (int i = 0; i < 10; i++)
            {
                var shape = factory.CreateShape();
                total += shape.CalculateArea();
                Console.WriteLine(GetShapeInfo(shape));
            }

            Console.WriteLine($"\n总面积：{total:F2}");
            Console.ReadKey();
        }

        static string GetShapeInfo(Shape shape)
        {
            if (shape is Square s) return $"正方形 边长:{s.Length} 面积:{s.CalculateArea()}";
            if (shape is Rectangle r) return $"长方形 长:{r.Length} 宽:{r.Width} 面积:{r.CalculateArea()}";
            if (shape is Triangle t) return $"三角形 边:[{t.A},{t.B},{t.C}] 面积:{t.CalculateArea():F2}";
            return "未知形状";
        }
    }
}